﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TestOnlineProject.Models.Entities;
using TestOnlineProject.Common;
using TestOnlineProject.Models.DataAccess;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace TestOnlineProject.Models.BusinessLogic
{
    public class QuestionBLO
    {
        QuestionDAO questionDAO = new QuestionDAO();
        AnswerDAO answerDAO = new AnswerDAO();
        UserTestDAO userTestDAO = new UserTestDAO();
        UserAnswerDAO userAnswerDao = new UserAnswerDAO();
        QuestionTypeDAO questionTypeDAO = new QuestionTypeDAO();
        SectionDAO sectionDAO = new SectionDAO();
        ParticipantDAO participantDAO = new ParticipantDAO();
        SectionQuestionDAO sectionQuestionDAO = new SectionQuestionDAO();

        /// <summary>
        /// Select question list.
        /// </summary>
        /// <param name="page">Number of page</param>
        /// <param name="createdBy">Category id</param>
        /// <param name="actualUser">Actual user key word</param>
        /// <param name="questionContent">Question content key word</param>
        /// <param name="column">Column name</param>
        /// <param name="sort">Sory type</param>
        /// <returns>Question list</returns>

        public List<Question> ToList(ref List<NoModel> noList, int? page, string keyWord = "", int questionTypeId = 0, string createdBy = "", int actualUser = 0, int subjectId = 0, int sectionId = 0, string column = "", string sort = "")
        {
            try
            {
                List<Question> questions = new List<Question>();

                // Search by SubjectId.
                questions = questionDAO.Select().Where(q => q.SubjectId == subjectId).OrderBy(q => q.QuestionId).ToList();

                // Just get all activated questions and owner's questions.
                if (!HttpContext.Current.User.IsInRole("1"))
                {
                    questions = questions.Where(q => q.IsActivated == true).ToList();
                }

                // Search by 'Created By'.
                if (createdBy == "")
                {
                    questions = questions.ToList();
                }
                if (createdBy == "mine")
                {
                    questions = questions.Where(q => q.UserId == int.Parse(HttpContext.Current.User.Identity.Name)).ToList();
                }
                if (createdBy == "admin")
                {
                    questions = questions.Where(q => (q.User.Role.Name == "Admin")).ToList();
                }
                if (createdBy == "teachers")
                {
                    questions = questions.Where(q => (q.User.Role.Name == "Teacher")).ToList();
                }
                if (createdBy == "students")
                {
                    questions = questions.Where(q => (q.User.Role.Name == "Student")).ToList();
                }
                if (createdBy == "actualUser")
                {
                    questions = questions.Where(q => ((q.User.UserId == actualUser))).ToList();
                }

                // Search by question type.
                if (questionTypeId > 0)
                {
                    questions = questions.Where(q => q.QuestionTypeId == questionTypeId).ToList();
                }

                // Search by keyWord.
                questions = questions.Where(q => q.Title.ToLower().Contains(keyWord.ToLower())).ToList();


                // Search by Section.
                if (sectionId > 0)
                {
                    var section = sectionDAO.SelectBySectionId(sectionId);
                    if (section.IsActivated)
                    {
                        int[] questionIds = section.SectionQuestions.Select(s => s.QuestionId).ToArray();
                        questions = questions.Where(q => questionIds.Contains(q.QuestionId)).ToList();
                    }
                }

                // Sort.
                switch (column + sort)
                {
                    case "NoAsc":
                        questions = questions.OrderBy(q => q.QuestionId).ToList();
                        break;
                    case "NoDesc":
                        questions = questions.OrderByDescending(q => q.QuestionId).ToList();
                        break;
                    case "QuestionTypeAsc":
                        questions = questions.OrderBy(q => q.QuestionType.Name).ToList();
                        break;
                    case "QuestionTypeDesc":
                        questions = questions.OrderByDescending(q => q.QuestionType.Name).ToList();
                        break;
                    case "SubjectAsc":
                        questions = questions.OrderBy(q => q.Subject.Name).ToList();
                        break;
                    case "SubjectDesc":
                        questions = questions.OrderByDescending(q => q.Subject.Name).ToList();
                        break;
                    case "TitleAsc":
                        questions = questions.OrderBy(q => q.Content).ToList();
                        break;
                    case "TitleDesc":
                        questions = questions.OrderByDescending(q => q.Content).ToList();
                        break;
                    case "UserAsc":
                        questions = questions.OrderBy(q => q.User.FullName).ToList();
                        break;
                    case "UserDesc":
                        questions = questions.OrderByDescending(q => q.User.FullName).ToList();
                        break;
                    case "CreatedTimeAsc":
                        questions = questions.OrderBy(q => q.CreatedTime).ToList();
                        break;
                    case "CreatedTimeDesc":
                        questions = questions.OrderByDescending(q => q.CreatedTime).ToList();
                        break;
                    case "LastEditedTimeAsc":
                        questions = questions.OrderBy(q => q.LastEditedTime).ToList();
                        break;
                    case "LastEditedTimeDesc":
                        questions = questions.OrderByDescending(q => q.LastEditedTime).ToList();
                        break;
                    case "IsActivatedAsc":
                        questions = questions.OrderBy(q => q.IsActivated).ToList();
                        break;
                    case "IsActivatedDesc":
                        questions = questions.OrderByDescending(q => q.IsActivated).ToList();
                        break;
                    default:
                        break;
                }

                // Generate no. List.
                foreach (var q in questions)
                {
                    noList.Add(new NoModel() { Id = q.QuestionId });
                }
                noList = noList.OrderBy(q => q.Id).ToList();
                for (int i = 0; i < noList.Count; i++)
                {
                    noList[i].No = i + 1;
                }

                return questions;
            }
            catch (Exception)
            {
                throw;
            }
        }


        public List<Question> ToList()
        {
            try
            {
                var questions = questionDAO.Select();
                return questions;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public List<Question> Recommend()
        {
            try
            {
                var list = questionDAO.Select().Where(q => q.IsActivated).OrderByDescending(q => q.QuestionId).ToList();
                if (!HttpContext.Current.User.IsInRole("1"))
                {
                    list = list.Where(q => q.Subject.Participants.Where(p => p.IsActivated && p.UserId == int.Parse(HttpContext.Current.User.Identity.Name)).ToList().Count > 0 && q.Subject.IsActivated).ToList();
                }
                return list;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public bool CheckAccessible(int userId, int subjectId, int questionId = 0, bool modify = false)
        {
            try
            {
                // Admin can  access.
                if (HttpContext.Current.User.IsInRole("1"))
                {
                    return true;
                }

                var question = questionDAO.SelectByQuestionId(questionId);

                // When search.
                if (question == null)
                {
                    var participant = participantDAO.SelectByUserIdSubjectId(userId, subjectId);
                    if (participant != null)
                    {
                        if (participant.IsActivated && participant.Subject.IsActivated && participant.User.IsActivated)
                        {
                            return true;
                        }
                    }
                }

                    // Details, edit.
                else
                {
                    var participant = participantDAO.SelectByUserIdSubjectId(userId, subjectId);
                    if (participant != null)
                    {
                        if (participant.IsActivated && participant.Subject.IsActivated && participant.User.IsActivated)
                        {
                            // Owner can access.
                            if (question.UserId == userId)
                            {
                                return true;
                            }
                            // Others access.
                            if (!modify && question.IsActivated)
                            {
                                return true;
                            }

                        }
                    }
                }

                return false;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Add new Question.
        /// </summary>
        /// <param name="questionModel"></param>
        /// <returns></returns>

        public int Add(QuestionModel questionModel)
        {
            try
            {
                int result = 0;

                var question = ConvertQuestionModelToQuestion(questionModel);
                // Question type is single choice or true/false.
                if (questionModel.QuestionTypeId == 1 || questionModel.QuestionTypeId == 4)
                {
                    // Validate.
                    // If number of answers < 2, return error.
                    if (questionModel.Answers.Count < 2)
                    {
                        // You must enter at least 2 answer.
                        return -2;
                    }

                    // If number of answers > 10, return error.
                    if (questionModel.Answers.Count > 10)
                    {
                        // You must enter at least 2 answer.
                        return -6;
                    }

                    // If no correct answer selected, return error.
                    var isSelect = false;
                    foreach (var a in questionModel.Answers)
                    {
                        if (a.Checked)
                        {
                            isSelect = true;
                        }
                    }
                    if (!isSelect)
                    {
                        // You must select a correct answer.
                        return -3;
                    }

                    // Update question.


                    result = questionDAO.Insert(question);
                    questionModel.QuestionId = question.QuestionId;

                }

                // Question type is multiple choice.
                if (questionModel.QuestionTypeId == 2)
                {
                    // Validate.
                    // If number of answers < 2, return error.
                    if (questionModel.Answers.Count < 2)
                    {
                        // You must enter at least 2 answer.
                        return -2;
                    }

                    // If number of answers > 10, return error.
                    if (questionModel.Answers.Count > 10)
                    {
                        // You must enter at least 2 answer.
                        return -6;
                    }
                    // Check total grade.
                    double totalGrade = 0;
                    foreach (var a in questionModel.Answers)
                    {
                        if (a.Grade >= 0)
                        {
                            totalGrade += a.Grade;
                        }
                    }
                    if (Math.Round(totalGrade) != 100)
                    {
                        // The positive grades you have chosen do not add up to 100%.
                        return -4;
                    }

                    // Update question.
                    //var question1 = ConvertQuestionModelToQuestion(questionModel);

                    result = questionDAO.Insert(question);
                    questionModel.QuestionId = question.QuestionId;

                }

                // Question type is single choice or matching.
                if (questionModel.QuestionTypeId == 3)
                {


                    // Validate.
                    // If number of answers < 2, return error.
                    if (questionModel.Answers.Count < 2)
                    {
                        // You must enter at least 2 answers.
                        return -2;
                    }

                    // If number of answers > 10, return error.
                    if (questionModel.Answers.Count > 10)
                    {
                        // You must enter at least 2 answer.
                        return -6;
                    }
                    // If number of matches < 3, return error.
                    if (questionModel.Matchs.Count < 3)
                    {
                        // You must enter at least 3 matches.
                        return -5;
                    }


                    // update question.
                    result = questionDAO.Insert(question);
                    questionModel.QuestionId = question.QuestionId;

                }
                if (result > 0 && (questionModel.SectionId != 0))
                {
                    SectionQuestionDAO sectionQuestionDAO = new SectionQuestionDAO();
                    sectionQuestionDAO.Insert(new SectionQuestion
                    {
                        QuestionId = question.QuestionId,
                        SectionId = questionModel.SectionId
                    });
                }
                return result;

            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Modify question.
        /// </summary>
        /// <param name="questionModel"></param>
        /// <returns></returns>

        public int Modify(QuestionModel questionModel)
        {
            try
            {
                int result = 0;
                var oldQuestion = questionDAO.SelectByQuestionId(questionModel.QuestionId);
                var question = ConvertQuestionModelToQuestion(questionModel);

                if (!question.LastEditedTime.ToString().Equals(oldQuestion.LastEditedTime.ToString()))
                {
                    // out of date
                    return -1;
                }
                question.LastEditedTime = DateTime.Now;

                // Question type is single choice or true/false.
                if (questionModel.QuestionTypeId == 1 || questionModel.QuestionTypeId == 4)
                {
                    // Validate.
                    // If number of answers < 2, return error.
                    if (questionModel.Answers.Count < 2)
                    {
                        // You must enter at least 2 answer.
                        return -2;
                    }

                    // If number of answers > 10, return error.
                    if (questionModel.Answers.Count > 10)
                    {
                        // You must enter at least 2 answer.
                        return -6;
                    }
                    // Validate.
                    // If no correct answer selected, return error.
                    var isSelect = false;
                    foreach (var a in questionModel.Answers)
                    {
                        if (a.Checked)
                        {
                            isSelect = true;
                        }
                    }
                    if (!isSelect)
                    {
                        // You must select a correct answer.
                        return -3;
                    }

                    // Update question.


                    result = questionDAO.Update(question);
                    questionModel.QuestionId = question.QuestionId;

                }

                // Question type is multiple choice.
                if (questionModel.QuestionTypeId == 2)
                {
                    // Validate.
                    // If number of answers < 2, return error.
                    if (questionModel.Answers.Count < 2)
                    {
                        // You must enter at least 2 answer.
                        return -2;
                    }

                    // If number of answers > 10, return error.
                    if (questionModel.Answers.Count > 10)
                    {
                        // You must enter at least 2 answer.
                        return -6;
                    }

                    // Check total grade.
                    double totalGrade = 0;
                    foreach (var a in questionModel.Answers)
                    {
                        if (a.Grade >= 0)
                        {
                            totalGrade += a.Grade;
                        }
                    }
                    if (Math.Round(totalGrade) != 100)
                    {
                        // The positive grades you have chosen do not add up to 100%.
                        return -4;
                    }

                    // Update question.
                    //var question1 = ConvertQuestionModelToQuestion(questionModel);

                    result = questionDAO.Update(question);
                    questionModel.QuestionId = question.QuestionId;

                }

                // Question type is single choice or matching.
                if (questionModel.QuestionTypeId == 3)
                {


                    // Validate.
                    // If number of answers < 2, return error.
                    if (questionModel.Answers.Count < 2)
                    {
                        // You must enter at least 2 answers.
                        return -2;
                    }

                    // If number of answers > 10, return error.
                    if (questionModel.Answers.Count > 10)
                    {
                        // You must enter at least 2 answer.
                        return -6;
                    }

                    // If number of matches < 3, return error.
                    if (questionModel.Matchs.Count < 3)
                    {
                        // You must enter at least 3 matches.
                        return -5;
                    }

                    // update question.
                    result = questionDAO.Update(question);
                    questionModel.QuestionId = question.QuestionId;

                }

                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Parse text file
        /// </summary>
        /// <param name="firstFile"></param>
        /// <param name="createrId"></param>
        /// <returns></returns>
        /// 

        public bool ParseFile(String firstFile, int createrId, int subjectId, out int successQuestion, out int dublicateQuestion, out Exception ex, int sectionId = 0)
        {
            int allQuestion = 0;
            dublicateQuestion = 0;
            successQuestion = 0;
            List<Question> questionList = new List<Question>();
            const Int32 BufferSize = 128;
            bool startQuestion = false, //start question
                 endQuestion = false, //end question
                 startAnswer = false, //start answer
                 fetchingAnswer = false, //after start answer and before end question
                 gotAnswer = false; //after get first answer and before end question
            string content = "", line = "";
            float grade = 0;
            var questionTitle = "";
            int lineCount = 0;
            var currentTime = DateTime.Now;
            String multipleChoisePattern = @"^\~{1}%-?\d+[.,]?\d*%";
            Regex reg = new Regex(multipleChoisePattern);
            try
            {
                EnumModel.QuestionType currentQuestionType = EnumModel.QuestionType.Undefined;
                List<string> answers = new List<string>();
                List<string> answersCharacter = new List<string>();
                bool stateValid = false;
                using (var fileStream = System.IO.File.OpenRead(firstFile))
                {
                    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
                    {
                        List<String> lineCache = new List<string>();
                        while ((line = streamReader.ReadLine()) != null)
                        {
                            line = line.Trim();
                            if (String.IsNullOrEmpty(line))
                            {
                                continue;
                            }
                            //Begin parse question
                            //check begin question when the question before dont have "}"
                            if (line.IndexOf("::") == 0 && line.LastIndexOf("::") > 0)
                            {
                                if (startQuestion == true)
                                {
                                    if (String.IsNullOrEmpty(content))
                                    {
                                        content = lineCache[0];
                                    }
                                    questionTitle = content.Length > 0 ? content.Substring(0, content.IndexOf("::", 3) > 0 ? content.IndexOf("::", 3) + 2 : 15) : "";

                                    if (String.IsNullOrEmpty(questionTitle))
                                    {
                                        questionTitle = content;
                                    }
                                    ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nPlease check '}' character.");
                                    return false;
                                }
                                else
                                {
                                    questionTitle = line.Length > 0 ? line.Substring(0, line.IndexOf("::", 3) > 0 ? line.IndexOf("::", 3) + 2 : 15) : "";
                                    startQuestion = true;
                                }
                            }
                            if (line.IndexOf("{") >= 0 && line.Length == 1)
                            {
                                startAnswer = true;
                            }
                            if (line.IndexOf("}") >= 0 && line.Length == 1)
                            {
                                endQuestion = true;
                            }

                            //Special trick for true/false case
                            if (CheckTrueFalseAnswer(line))
                            {
                                startAnswer = true;
                                endQuestion = true;
                                fetchingAnswer = true;
                            }

                            if ((!startQuestion) && (!startAnswer) && (!endQuestion))
                            {
                                lineCache.Add(line);
                            }
                            if (startQuestion && (!startAnswer) && (!endQuestion))
                            {
                                content += line;
                            }

                            else if (startQuestion && startAnswer && (!endQuestion))
                            {
                                if (line.IndexOf("{") == 0)
                                {
                                    fetchingAnswer = true;
                                }
                                else
                                {
                                    if (fetchingAnswer)
                                    {
                                        if ((line.IndexOf("=") == 0) || (line.IndexOf("~") == 0))
                                        {
                                            gotAnswer = true;
                                            answers.Add(line);
                                            answersCharacter.Add(line[0].ToString());
                                        }
                                        else
                                        {
                                            if (answers.Count > 0)
                                            {
                                                answers[answers.Count - 1] += line;
                                            }
                                            else
                                            {
                                                if (answers.Count == 0)
                                                {
                                                    ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nPlease check '=' or '~' character.");
                                                    return false;
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            //True/False Question format
                            else if (startQuestion && startAnswer && endQuestion && fetchingAnswer && CheckTrueFalseAnswer(line))
                            {
                                content += line;
                                answers.Add(line.Substring(line.IndexOf("{") + 1).Replace("}", " ").Trim());
                                gotAnswer = true;
                                if (!(answers[answers.Count - 1].Equals("F", StringComparison.CurrentCultureIgnoreCase) || answers[answers.Count - 1].Equals("T", StringComparison.CurrentCultureIgnoreCase)))
                                {
                                    if (String.IsNullOrEmpty(content))
                                    {
                                        content = lineCache[0];
                                    }
                                    questionTitle = content.Length > 0 ? content.Substring(0, content.IndexOf("::", 3) > 0 ? content.IndexOf("::", 3) + 2 : 15) : "";
                                    if (String.IsNullOrEmpty(questionTitle))
                                    {
                                        questionTitle = content;
                                    }
                                    ex = new Exception("File not valid at line " + lineCount + ". Question: " + questionTitle + "\nPlease check true/false structure.");
                                    return false;
                                }
                            }

                            // Validate file
                            stateValid = ValidateFile(startQuestion, endQuestion, startAnswer, fetchingAnswer, gotAnswer);
                            if (!stateValid)
                            {
                                if (String.IsNullOrEmpty(content))
                                {
                                    content = lineCache[0];
                                }
                                questionTitle = content.Length > 0 ? content.Substring(0, content.IndexOf("::", 3) > 0 ? content.IndexOf("::", 3) + 2 : 15) : "";
                                if (String.IsNullOrEmpty(questionTitle))
                                {
                                    questionTitle = content;
                                }
                                ex = new Exception("File not valid near line " + lineCount + " .Question: " + questionTitle + "\nPlease check '{' character or title of question.");

                                return false;
                            }

                            // Define Question Type
                            if (startQuestion && startAnswer && endQuestion)
                            {
                                var count = answersCharacter.Count(c => c == "=");
                                if (count == 1)
                                {
                                    currentQuestionType = EnumModel.QuestionType.SingleChoise;
                                }
                                else if (count == 0 && answersCharacter.Count > 0)
                                {
                                    currentQuestionType = EnumModel.QuestionType.MultiChoise;
                                }
                                else if (count == 0 && answers.Count == 1)
                                {
                                    currentQuestionType = EnumModel.QuestionType.TrueFalse;
                                }
                                else if (count > 1)
                                {
                                    currentQuestionType = EnumModel.QuestionType.Matching;
                                }
                                // get Question title
                                if (questionTitle.Length > 0)
                                {
                                    questionTitle = questionTitle.Replace(":", "");
                                }

                                TestOnlineProject.Models.Entities.Question question = new Models.Entities.Question
                                {
                                    Content = FilterContent(content),
                                    UserId = createrId,
                                    SubjectId = subjectId,
                                    Title = questionTitle,
                                    CreatedTime = currentTime,
                                    LastEditedTime = currentTime,
                                    IsActivated = true,
                                    QuestionTypeId = (int)currentQuestionType
                                };

                                for (int i = 0; i < answers.Count; i++)
                                {
                                    TestOnlineProject.Models.Entities.Answer answer = new Models.Entities.Answer();

                                    #region grade
                                    if (currentQuestionType == EnumModel.QuestionType.SingleChoise)
                                    {
                                        if (answersCharacter[i] == "=")
                                        {
                                            grade = 100;
                                        }
                                        else
                                        {
                                            grade = 0;
                                        }
                                    }
                                    else if (currentQuestionType == EnumModel.QuestionType.MultiChoise)
                                    {
                                        if (reg.IsMatch(answers[i]))
                                        {
                                            grade = float.Parse(answers[i].Substring(answers[i].IndexOf("%") + 1, answers[i].IndexOf("%", answers[i].IndexOf("%") + 1) - answers[i].IndexOf("%") - 1), System.Threading.Thread.CurrentThread.CurrentCulture);
                                            grade = float.Parse(Math.Round(grade, 2).ToString());
                                        }
                                        else
                                        {
                                            ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nPlease check grade.");
                                            return false;
                                        }

                                    }
                                    else if (currentQuestionType == EnumModel.QuestionType.Matching)
                                    {
                                        grade = (float)Math.Round((double)100 / answers.Count, 2);

                                    }
                                    else if (currentQuestionType == EnumModel.QuestionType.TrueFalse)
                                    {
                                        grade = 100;
                                    }
                                    if (currentQuestionType == EnumModel.QuestionType.TrueFalse)
                                    {
                                        if (answers[i].IndexOf("T") >= 0)
                                        {
                                            answer.Content = "True";
                                            answer.Grade = answers[i].IndexOf("T") >= 0 ? 100 : 0;
                                            question.Answers.Add(new Answer
                                            {
                                                Content = "False",
                                                Grade = answers[i].IndexOf("T") >= 0 ? 0 : 100
                                            });
                                        }
                                        else if (answers[i].IndexOf("F") >= 0)
                                        {
                                            question.Answers.Add(new Answer
                                            {
                                                Content = "True",
                                                Grade = answers[i].IndexOf("F") >= 0 ? 0 : 100
                                            });
                                            answer.Content = "False";
                                            answer.Grade = answers[i].IndexOf("F") >= 0 ? 100 : 0;
                                        }
                                    }
                                    else if (currentQuestionType == EnumModel.QuestionType.Matching)
                                    {
                                        if (answers[i].IndexOf("->") < 0)
                                        {
                                            ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nPlease check '->' character.");
                                            return false;
                                        }
                                        question.Matches.Add(new TestOnlineProject.Models.Entities.Match
                                            {
                                                Content =
                                                    answers[i].Substring(answers[i].IndexOf("->") + 2,
                                                                         answers[i].Length - answers[i].IndexOf("->") - 2).Trim()
                                            });

                                        answer.Content =
                                            FilterContent(answers[i]).Substring(0,
                                                                                (answers[i].IndexOf("->") - 2) >= 0 ? answers[i].IndexOf("->") - 2 : 0).Trim();

                                        if (String.IsNullOrEmpty(question.Matches.Last().Content))
                                        {
                                            ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nPlease check match content.");
                                            return false;
                                        }

                                        if (!String.IsNullOrEmpty(answer.Content))
                                        {
                                            answer.Grade = grade;
                                            answer.Match = question.Matches.Last();
                                            question.Answers.Add(answer);
                                        }
                                    }
                                    else
                                    {
                                        answer.Content = FilterContent(answers[i]);
                                        answer.Grade = grade;
                                    }

                                    if (currentQuestionType != EnumModel.QuestionType.Matching)
                                    {
                                        question.Answers.Add(answer);
                                    }

                                    #endregion
                                }

                                //ReUpdate grade for match type
                                if (currentQuestionType == EnumModel.QuestionType.Matching)
                                {
                                    var number = Math.Round((double)100 / question.Answers.Count, 2);
                                    foreach (var ans in question.Answers)
                                    {
                                        ans.Grade = number;
                                    }
                                }

                                //Validate total percent for multiple choise case 
                                if (currentQuestionType == EnumModel.QuestionType.MultiChoise)
                                {
                                    double checkGrade = 0;
                                    for (int j = 0; j < question.Answers.Count; j++)
                                    {
                                        if (question.Answers.ElementAt(j).Grade > 0)
                                        {
                                            checkGrade += question.Answers.ElementAt(j).Grade;
                                        }
                                    }
                                    if (Math.Round(checkGrade) != 100)
                                    {
                                        ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nThe positive grades do not add up to 100%.");
                                        return false;
                                    }
                                }

                                // ValidateFile length
                                // Title content
                                if (questionTitle.Length < 5 || questionTitle.Length > 100)
                                {
                                    ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nThe Title length is 5-100 characters.");
                                    return false;
                                }

                                // Question content
                                if (question.Content.Length < 5 || question.Content.Length > 500)
                                {
                                    ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nThe Question length is 5-500 characters.");
                                    return false;
                                }

                                // Number of Answer
                                if (question.Answers.Count > 10)
                                {
                                    ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nYou have only 10 answers.");
                                    return false;
                                }

                                if (question.Answers.Count < 2)
                                {
                                    ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nYou must enter at least 2 answers.");
                                    return false;
                                }

                                // Answer content
                                foreach (var ans in question.Answers)
                                {
                                    if (ans.Content.Length < 1 || ans.Content.Length > 500)
                                    {
                                        ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nThe Answer length is 1-500 characters.");
                                        return false;
                                    }
                                }

                                // Validate match
                                if (currentQuestionType == EnumModel.QuestionType.Matching)
                                {
                                    foreach (var mat in question.Matches)
                                    {
                                        if (mat.Content.Length < 1 || mat.Content.Length > 100)
                                        {
                                            ex = new Exception("File not valid near line " + lineCount + ".Question: " + questionTitle + "\nThe Match length is 1-100 characters.");
                                            return false;
                                        }
                                    }
                                }
                                //allQuestion = questionList.Count;
                                allQuestion++;
                                CheckDublicateQuestion check = new CheckDublicateQuestion();
                                var exist = check.CheckDublicate(questionList, question);
                                
                                if (exist == false)
                                {
                                    questionList.Add(question);
                                }
                                
                                //Clear buffer
                                answers.Clear();
                                answersCharacter.Clear();
                                content = "";
                                startQuestion = false;
                                startAnswer = false;
                                endQuestion = false;
                                fetchingAnswer = false;
                                gotAnswer = false;
                                lineCache.Clear();
                                currentQuestionType = EnumModel.QuestionType.Undefined;
                            }
                            lineCount++;
                        }
                    }
                }
                ex = null;
                
                //File.Delete(filepath);
                
                // Insert to questionDAO

                questionList = questionDAO.Insert(questionList, createrId);
                successQuestion = questionList.Count;
                dublicateQuestion = allQuestion - successQuestion;
                // Insert to Section
                if (sectionId > 0)
                {
                    foreach (var question in questionList)
                    {
                        var sectionQuestion = new SectionQuestion()
                            {
                                SectionId = sectionId,
                                QuestionId = question.QuestionId
                            };
                        sectionQuestionDAO.Insert(sectionQuestion);
                    }
                }
                return true;
            }
            catch (Exception exception)
            {
                //File.Delete(filepath);
                throw new Exception(exception.Message + "questionTitle" + questionTitle + "lineCount" + lineCount, exception);
            }
        }

        private bool ValidateFile(bool startQuestion, bool endQuestion, bool startAnswer, bool fetchingAnswer, bool gotAnswer)
        {
            //do not have "::"
            if (!startQuestion && startAnswer)
            {
                return false;
            }
            //dont have "{" character
            if (startQuestion && !startAnswer && endQuestion)
            {
                return false;
            }
            //do not have answer
            if (startQuestion && startAnswer && fetchingAnswer && !gotAnswer && endQuestion)
            {
                return false;
            }

            return true;
        }

        private bool CheckTrueFalseAnswer(String line)
        {
            string TrueFalseAnswerCache = "";
            if (TrueFalseAnswerCache == line)
            {
                return true;
            }
            try
            {
                if (line.IndexOf("}") >= 0 && line.IndexOf("{") >= 0)
                {
                    var answer = line.Substring(line.IndexOf("{") + 1, line.IndexOf("}") - line.IndexOf("{") - 1).Trim();
                    if (answer.Length == 1)
                    {
                        TrueFalseAnswerCache = line;
                        return true;
                    }
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        private string GetTrueFalseAnswer(String line)
        {
            string TrueFalseAnswer = "";
            string GetTrueFalseAnswerCache = "";
            if (GetTrueFalseAnswerCache == line)
            {
                return TrueFalseAnswer;
            }
            try
            {
                if (line.IndexOf("}") >= 0 && line.IndexOf("{") >= 0)
                {
                    var answer = line.Substring(line.IndexOf("{") + 1, line.IndexOf("}") - line.IndexOf("{") - 1).Trim();
                    if (answer.Equals("F", StringComparison.CurrentCultureIgnoreCase) || answer.Equals("T", StringComparison.CurrentCultureIgnoreCase))
                    {
                        GetTrueFalseAnswerCache = line;
                        TrueFalseAnswer = answer;
                        return TrueFalseAnswer;
                    }
                }
                return line;
            }
            catch
            {
                return line;
            }
        }

        private string FilterContent(string content)
        {
            content = content.Trim();
            if (content[0] == '=' || content[0] == '~')
            {
                content = content.Substring(1);
            }

            if (content[0] == '%' && (content.IndexOf('%', 2) > 0 && content.IndexOf('%', 2) < 12))
            {
                content = content.Substring(content.IndexOf('%', 2) + 1);
            }
            if (content[content.Length - 1] == '}')
            {
                if (content.IndexOf("{", content.Length - 5) > 0)
                {
                    content = content.Substring(0, content.IndexOf("{", content.Length - 5));
                }
            }
            if (content.IndexOf("::") >= 0 && content.IndexOf("::", content.IndexOf("::") + 1) > 0)
            {
                content = content.Substring(content.IndexOf("::", content.IndexOf("::") + 1) + 2);
            }
            return content;
        }

        

        private Question ConvertQuestionModelToQuestion(QuestionModel questionModel)
        {
            try
            {
                // Convert QuestionModel object to Question.
                // 1
                // Question details.
                Question question = new Question();
                question.QuestionId = questionModel.QuestionId;
                question.QuestionTypeId = questionModel.QuestionTypeId;
                question.SubjectId = questionModel.SubjectId;
                question.UserId = int.Parse(HttpContext.Current.User.Identity.Name);
                question.Content = questionModel.Content;
                question.Title = questionModel.Title;
                question.Explanation = questionModel.Explanation;
                if (questionModel.QuestionId > 0)
                {
                    question.CreatedTime = questionDAO.SelectByQuestionId(questionModel.QuestionId).CreatedTime;
                }
                else
                {
                    question.CreatedTime = DateTime.Now;
                }
                if (questionModel.QuestionId > 0)
                {
                    question.LastEditedTime = questionModel.LastEditedTime;
                }
                else
                {
                    question.LastEditedTime = DateTime.Now;
                }
                question.IsActivated = true;

                // 2
                // Answer details.
                // QuestionType is Single choice or true/false.
                if (questionModel.QuestionTypeId == 1 || questionModel.QuestionTypeId == 4)
                {

                    // Create answers.
                    foreach (var a in questionModel.Answers)
                    {
                        Answer answer = new Answer();
                        answer.QuestionId = questionModel.QuestionId;
                        answer.Content = a.Content;
                        if (a.Checked)
                        {
                            answer.Grade = 100;
                        }
                        else
                        {
                            answer.Grade = 0;
                        }
                        question.Answers.Add(answer);
                    }
                }

                // QuestionType is multiple choice.
                if (questionModel.QuestionTypeId == 2)
                {
                    // Create answers.
                    foreach (var a in questionModel.Answers)
                    {
                        Answer answer = new Answer();
                        answer.QuestionId = questionModel.QuestionId;
                        answer.Content = a.Content;
                        answer.Grade = a.Grade;
                        question.Answers.Add(answer);
                    }

                }

                // QuestionType is matching.
                if (questionModel.QuestionTypeId == 3)
                {
                    // Create answers.
                    double count = (questionModel.Answers.Count);
                    foreach (var a in questionModel.Answers)
                    {
                        Answer answer = new Answer();
                        answer.QuestionId = questionModel.QuestionId;
                        answer.Content = a.Content;
                        answer.Grade = 1 / count * 100;
                        question.Answers.Add(answer);
                    }

                    // Group "invalid matches" and matches into one.
                    if (questionModel.InvalidMatchs != null)
                    {
                        foreach (var m in questionModel.InvalidMatchs)
                        {
                            questionModel.Matchs.Add(m);
                        }
                    }

                    // Create matches.
                    foreach (var a in questionModel.Matchs)
                    {
                        TestOnlineProject.Models.Entities.Match match = new TestOnlineProject.Models.Entities.Match();
                        match.QuestionId = questionModel.QuestionId;
                        match.Content = a.Content;
                        question.Matches.Add(match);
                    }


                }

                return question;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Convert Question To QuestionModel.
        /// </summary>
        /// <param name="questionId"></param>
        /// <returns></returns>

        public QuestionModel ConvertQuestionToQuestionModel(int questionId)
        {
            try
            {
                var questionModel = new QuestionModel();
                var question = questionDAO.SelectByQuestionId(questionId);

                // Convert question.
                questionModel.QuestionId = question.QuestionId;
                questionModel.QuestionTypeId = question.QuestionTypeId;
                //questionModel.SectionId = question.SectionId;
                questionModel.SubjectId = question.SubjectId;
                questionModel.Title = question.Title;
                questionModel.Content = question.Content;
                questionModel.CreatedTime = question.CreatedTime;
                questionModel.LastEditedTime = question.LastEditedTime;
                questionModel.Explanation = question.Explanation;

                // Convert answer depend on QuestionType.
                var answerModelList = new List<AnswerModel>();
                var matchModelList = new List<MatchModel>();
                var invalidMatchModelList = new List<MatchModel>();

                // QuestionType is single choice, multiple choice, true/false.
                if (question.QuestionTypeId == 1 || question.QuestionTypeId == 2 || question.QuestionTypeId == 4)
                {
                    // Convert answers.
                    foreach (var a in question.Answers)
                    {
                        var answerModel = new AnswerModel();
                        answerModel.AnswerId = a.AnswerId;
                        answerModel.Content = a.Content;
                        if (a.Grade > 0)
                        {
                            answerModel.Checked = true;
                        }
                        else
                        {
                            answerModel.Checked = false;
                        }
                        answerModel.Grade = a.Grade;
                        answerModelList.Add(answerModel);
                    }
                    questionModel.Answers = answerModelList;
                    return questionModel;
                }

                if (question.QuestionTypeId == 3)
                {
                    // Convert to answer models.
                    foreach (var a in question.Answers)
                    {
                        var answerModel = new AnswerModel();
                        answerModel.AnswerId = a.AnswerId;
                        answerModel.Content = a.Content;
                        answerModel.Grade = a.Grade;
                        if (a.MatchId != null)
                        {
                            answerModel.MatchId = a.MatchId.Value;
                        }
                        answerModelList.Add(answerModel);
                    }
                    questionModel.Answers = answerModelList;

                    // Convert to match models.
                    if (question.Matches != null)
                    {
                        //foreach (var m in question.Matches)
                        //{
                        //    var matchModel = new MatchModel();
                        //    matchModel.MatchId = m.MatchId;
                        //    matchModel.Content = m.Content;
                        //    matchModelList.Add(matchModel);
                        //}

                        for (var i = 0; i < question.Answers.Count; i++)
                        {
                            var matchModel = new MatchModel();
                            matchModel.MatchId = question.Matches.ToList()[i].MatchId;
                            matchModel.Content = question.Matches.ToList()[i].Content;
                            matchModelList.Add(matchModel);
                        }
                        questionModel.Matchs = matchModelList;

                        for (var i = question.Answers.Count; i < question.Matches.Count; i++)
                        {
                            var matchModel = new MatchModel();
                            matchModel.MatchId = question.Matches.ToList()[i].MatchId;
                            matchModel.Content = question.Matches.ToList()[i].Content;
                            invalidMatchModelList.Add(matchModel);
                        }
                        questionModel.InvalidMatchs = invalidMatchModelList;
                    }


                    return questionModel;
                }

                // QuestionType is matching.
                //


                return questionModel;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Find question.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>

        public Question Find(int id)
        {
            try
            {
                Question question = questionDAO.SelectByQuestionId(id);
                return question;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Deactivate questions.
        /// </summary>
        /// <param name="ids">Question ids string</param>
        /// <returns>Number of question has been deactivated</returns>

        public int Deactivate(string ids = "")
        {
            try
            {
                StringHelper spliter = new StringHelper();

                // Split id string to int array.
                int[] idInt = spliter.Split(ids);

                int result = 0;

                // Deactivate questions.
                foreach (var i in idInt)
                {
                    // Select question by id.
                    var question = questionDAO.SelectByQuestionId(i);

                    if (HttpContext.Current.User.IsInRole("1"))
                    {
                        // Check question is activated?
                        if (question.IsActivated)
                        {
                            question.IsActivated = false;
                            result += questionDAO.Deactivate(question.QuestionId);

                        }
                    }
                }

                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Activate questions
        /// </summary>
        /// <param name="ids">Question ids string</param>
        /// <returns>Number of question has been activated</returns>

        public int Activate(string ids = "")
        {
            try
            {
                StringHelper spliter = new StringHelper();

                // Split id string to int array.
                int[] idInt = spliter.Split(ids);

                int result = 0;

                // Deactivate questions.
                foreach (var i in idInt)
                {
                    // Select question by id.
                    var question = questionDAO.SelectByQuestionId(i);

                    if (HttpContext.Current.User.IsInRole("1"))
                    {
                        // check question is deactivated?
                        if (!question.IsActivated)
                        {
                            question.IsActivated = true;
                            result += questionDAO.Activate(question.QuestionId);
                        }
                    }
                }

                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Add Question to String
        /// </summary>
        /// <param name="ids">List Id of Question</param>
        /// <returns>String question</returns>

        public string ConvertQuestionToString(string ids)
        {
            try
            {
                var spliter = new StringHelper();
                var idInt = spliter.Split(ids);
                var result = "";

                foreach (var i in idInt)
                {
                    var questionModel = ConvertQuestionToQuestionModel(i);
                    var questionType = questionTypeDAO.SelectByQuestionTypeId(questionModel.QuestionTypeId);

                    result += questionModel.Content + "<br />";
                    result += "( " + questionType.Name + " )<br />";
                    result += "<ol>";

                    for (var j = 0; j < questionModel.Answers.Count; j++)
                    {
                        result += "<li>" + questionModel.Answers[j].Content + "</li>";
                    }
                    result += "</ol><br />";

                    if (questionModel.QuestionTypeId == 3)
                    {
                        result += "<ol>";
                        for (var j = 0; j < questionModel.Matchs.Count; j++)
                        {
                            result += "<li>" + questionModel.Matchs[j].Content + "</li>";
                        }
                        result += "</ol><br />";
                    }
                }
                return result;
            }
            catch (Exception)
            {
                return "";
            }
        }

        /// <summary>
        /// Remove questions.
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>

        public int Remove(string ids = "")
        {
            try
            {
                StringHelper spliter = new StringHelper();

                // Split id string to int array.
                int[] idInt = spliter.Split(ids);

                int result = 0;

                // Delete questions.
                foreach (var i in idInt)
                {
                    var question = questionDAO.SelectByQuestionId(i);
                    if (HttpContext.Current.User.IsInRole("1") || int.Parse(HttpContext.Current.User.Identity.Name) == question.UserId)
                    {
                        if (!CheckIsUsingQuestion(i))
                        {
                            result += questionDAO.Delete(i);
                        }
                        else
                        {
                            // The questions is using.
                            result = -1;
                            break;
                        }
                    }
                }

                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public bool CheckIsUsingQuestion(int questionId)
        {
            try
            {
                var result = false;

                var userTests = userTestDAO.Select().Where(ut => ut.TestId != null);
                if (userTests.Count() > 0)
                {
                    userTests = userTests.Where(ut => (ut.StartTime.AddMinutes(ut.Test.Duration + 3) > DateTime.Now && ut.FinishTime == null)).ToList();
                }
                if (userTests.Count() == 0)
                {
                    return false;
                }

                foreach (var ut in userTests)
                {
                    int[] ids = ut.Test.TestQuestions.Select(q => q.QuestionId).ToArray();
                    var questions = questionDAO.Select().Where(q => ids.Contains(q.QuestionId)).ToList();
                    if (questions.Count > 0)
                    {
                        result = true;
                        break;
                    }
                }

                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Search Question with keyWord
        /// </summary>
        /// <param name="subjectId">Id of Subject</param>
        /// <param name="keyWord">keyWord to search</param>
        /// <returns>List Question</returns>

        public List<Question> ToList(ref List<NoModel> noList, int subjectId, string keyWord)
        {
            try
            {
                // Lower keyWord
                keyWord = keyWord.Trim().ToLower();

                // Select list Question from SubjectId
                var questions = questionDAO.SelectBySubjectId(subjectId);

                // Select list Question with keyWord
                questions = questions.Where(x => x.Content.ToLower().Contains(keyWord)).ToList();

                // Generate no. List.
                foreach (var question in questions)
                {
                    noList.Add(new NoModel() { Id = question.QuestionId });
                }
                noList = noList.OrderBy(q => q.Id).ToList();
                for (var i = 0; i < noList.Count; i++)
                {
                    noList[i].No = i + 1;
                }

                return questions;
            }
            catch (Exception)
            {
                return null;
            }

        }

        /// <summary>
        /// Create column chart
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>

        public Tuple<List<int>, int> GenerateColumnChart(int id)
        {
            try
            {
                var answers = answerDAO.SelectByQuestionId(id);
                var listNum = new List<int>();
                var questionType = questionDAO.SelectByQuestionId(id).QuestionTypeId;
                if (answers != null)
                {
                    foreach (var answer in answers)
                    {
                        if (questionType == 3)
                        {
                            if (answer.MatchId != null)
                            {
                                var userAnswers = userAnswerDao.SelectByQuestionIdMatchId(id, (int)answer.MatchId);
                                listNum.Add(userAnswers != null ? userAnswers.Count() : 0);
                            }
                        }
                        else
                        {
                            var userAnswers = userAnswerDao.SelectByQuestionIdAnswerId(id, answer.AnswerId);
                            listNum.Add(userAnswers != null ? userAnswers.Count(u => u.IsSelected) : 0);
                        }
                    }
                    if(listNum.Sum()==0)
                    {
                        return new Tuple<List<int>, int>(null, 0);
                    }
                    return new Tuple<List<int>, int>(listNum, answers.Count());
                }
                return new Tuple<List<int>, int>(null, 0);
            }
            catch (Exception)
            {
                return new Tuple<List<int>, int>(null, 0);
            }
        }

        public Tuple<int, int, int[]> GeneratePieChart(int id)
        {
            try
            {
                var answers = answerDAO.SelectByQuestionId(id);
                var questionType = questionDAO.SelectByQuestionId(id).QuestionTypeId;
                var countTrue = 0;
                var countFalse = 0;
                var listTrue = new int[11];
                var answerMultiple = new List<Answer>();
                if (IsUserAnswer(id) > 0)
                {
                    if (questionType != 2 && questionType != 3)
                    {
                        countFalse += IsUserAnswer(id);
                    }
                    else
                    {
                        listTrue[0] += IsUserAnswer(id);
                    }
                }
                if (answers != null)
                {
                    foreach (var answer in answers)
                    {
                        // check single choice and true/false
                        if (questionType != 2 && questionType != 3)
                        {

                            if ((int)answer.Grade == 100)
                            {
                                var users = userAnswerDao.SelectByQuestionIdAnswerId(id, answer.AnswerId);
                                countTrue = users.Count(u => u.IsSelected);
                            }
                            else
                            {
                                var users = userAnswerDao.SelectByQuestionIdAnswerId(id, answer.AnswerId);
                                countFalse += users.Count(u => u.IsSelected);
                            }
                            // check multiple choice
                        }
                        else if (questionType == 2)
                        {
                            if ((int)answer.Grade > 0)
                            {
                                answerMultiple.Add(answer);
                            }
                        }
                    }
                    if (questionType == 2 || questionType == 3)
                    {
                        // Select users answered this question
                        var userAnswers = userAnswerDao.SelectByQuestionId(id);

                        // Select the test user taked
                        var userTests = userTestDAO.SelectUserTestId();
                        foreach (var userTest in userTests)
                        {
                            if (userAnswers.Select(u => u.UserTestId).ToList().Contains(userTest))
                            {
                                // MULTIPLE CHOICES
                                if (questionType == 2)
                                {
                                    // select the answers for the question in the test
                                    var answersOneQuestionPerTest = userAnswers.Where(u => u.UserTestId == userTest && u.IsSelected)
                                        .Select(u => u.AnswerId).ToList();

                                    // Compare with true answer
                                    if (answerMultiple.Count() == answersOneQuestionPerTest.Count())
                                    {
                                        bool checkTrue = true;
                                        foreach (var answerTrue in answerMultiple)
                                        {
                                            checkTrue = answersOneQuestionPerTest.Contains(answerTrue.AnswerId);
                                            if (!checkTrue)
                                            {
                                                break;
                                            }
                                        }
                                        if (checkTrue)
                                        {
                                            countTrue++;
                                        }
                                        else
                                        {
                                            countFalse++;
                                        }
                                    }
                                    else
                                    {
                                        countFalse++;
                                    }
                                }
                                // MATCHING
                                if (questionType == 3)
                                {
                                    // Select user's answers for 1 test
                                    var userAnswerPerTest = userAnswers.Where(u => u.UserTestId == userTest).ToList();

                                    // Compare quit true answers
                                    int count = 0;
                                    bool checkSelected = false;
                                    foreach (var answer in answers)
                                    {
                                        foreach (var userAnswer in userAnswerPerTest)
                                        {
                                            if (userAnswer.MatchId != null)
                                            {
                                                checkSelected = true;
                                                if (userAnswer.AnswerId == answer.AnswerId && userAnswer.MatchId == answer.MatchId)
                                                {
                                                    count++;
                                                }
                                            }
                                        }
                                    }
                                    if (checkSelected)
                                    {
                                        if (count >= 0 && count <= 10)
                                        {
                                            listTrue[count]++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return new Tuple<int, int, int[]>(countTrue, countFalse, listTrue);
            }
            catch (Exception)
            {
                return new Tuple<int, int, int[]>(0, 0, null);
            }
        }

        private int IsUserAnswer(int questionId)
        {

            // select all user take the test
            var usertests = userTestDAO.Select();
            int count = 0;

            foreach (var usertest in usertests)
            {
                // find user's answer for question
                var useranswers = userAnswerDao.SelectByUserTestIdQuestionId(usertest.UserTestId, questionId);
                if (useranswers.Count() != 0)
                {
                    bool checkSelected = false;
                    // Check user select one answers
                    foreach (var useranswer in useranswers)
                    {
                        if (useranswer.IsSelected)
                        {
                            checkSelected = true;
                        }
                    }
                    if (!checkSelected)
                    {
                        count++;
                    }
                }
            }
            return count;
        }

        public Tuple<List<int>, int> GenerateStakedColumnChart(int id)
        {
            try
            {
                // get answers for question
                var answers = answerDAO.SelectByQuestionId(id);
                // get matches for question
                var question = questionDAO.SelectByQuestionId(id);
                var matches = question.Matches;

                int count = matches.Count(); // number of matchs
                var userAnswers = new List<int>(); // list of count users choose match for answer
                foreach (var answer in answers)
                {
                    foreach (var match in matches)
                    {
                        var numUsers = userAnswerDao.SelectByQuestionIdAnswerIdMatchId(id, answer.AnswerId, match.MatchId);
                        userAnswers.Add(numUsers.Count());
                    }
                }
                return new Tuple<List<int>, int>(userAnswers, count);
            }
            catch (Exception)
            {
                return new Tuple<List<int>, int>(null, 0);
            }

        }

        public List<Question> ListImportedQuestion(int subjectId, int userId, int page = 1, int size = 10)
        {
            return questionDAO.ListImportedQuestion(subjectId, userId, page, size);
        }
    }
}